﻿#ifndef NETHEADER_H
#define NETHEADER_H

#include <QDebug>
#include <QQueue>
#include <QMutex>
#include <QMetaType>
#include <QWaitCondition>
#include <memory>

#define WAITSECONDS 2

#define MB (1024 * 1024)

#define LOG         qDebug().noquote() <<__FILE__<<__LINE__<<__FUNCTION__

#define MESG_TYPE_VAR_SIZE 2
#define MESG_SIZE_VAR_SIZE 4
#define MESG_IP_VAR_SIZE 4
#define MESG_HEAD_SIZE 11

#define MAX_QUEUE_DATA_COUNT 1500


enum MsgType {
    MsgType_ImgSend     = 0,
    MsgType_ImgRecv     = 1,
    MsgType_AudioSend   = 2,
    MsgType_AudioRecv   = 3,

    MsgType_TextSend        = 4,
    MsgType_TextRecv        = 5,
    MsgType_CreatMeeting    = 6,
    MsgType_ExitMeeting     = 7,
    MsgType_JoinMeeting     = 8,
    MsgType_CloseCamera     = 9,

    MsgType_CreatMeetingResponse = 20,
    MsgType_PartnerExit          = 21,
    MsgType_PartnerJoin          = 22,
    MsgType_JoinMeetingResponse  = 23,
    MsgType_PartnerJoin2         = 24,
    MsgType_RemoteHostClosedError= 40,
    MsgType_OtherNetError        = 41,
};

struct MESG
{
    MsgType                     type;
    quint32                     size;
    quint32                     ip;
    std::shared_ptr<uchar[]>     data;
};
Q_DECLARE_METATYPE(MESG*);

template<class T>
struct QUEUE_DATA
{
public:
    void push_msg(T* msg){
        m_mutex.lock();

        while (m_dataQueue.size() > MAX_QUEUE_DATA_COUNT) {
            m_waitCondition.wait(&m_mutex);
        }
        m_dataQueue.push_back(msg);

        m_mutex.unlock();
        m_waitCondition.wakeOne();
    }

    T* pop_msg() {
        m_mutex.lock();

        while (m_dataQueue.size() == 0) {
            auto flag = m_waitCondition.wait(&m_mutex, WAITSECONDS * 1000);
            if (!flag) {
                m_mutex.unlock();
                return nullptr;
            }
        }

        T* msg = m_dataQueue.front();
        m_dataQueue.pop_front();

        m_mutex.unlock();
        m_waitCondition.wakeOne();
        return msg;
    }

    void clear() {
        m_mutex.lock();
        m_dataQueue.clear();
        m_mutex.unlock();
    }

private:
    QQueue<T*>              m_dataQueue;
    QMutex                  m_mutex;
    QWaitCondition          m_waitCondition;
};

#endif // NETHEADER_H
